package com.example.baselib.imageLoader;

import com.example.baselib.utils.TextUtils;
import com.example.baselib.utils.ThreadUtils;
import com.example.baselib.utils.log.LogUtils;
import com.google.gson.Gson;
import ohos.agp.components.Image;
import ohos.app.Context;
import ohos.media.image.ImageSource;
import ohos.media.image.PixelMap;
import ohos.net.NetHandle;
import ohos.net.NetManager;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.Reference;
import java.lang.ref.SoftReference;
import java.net.HttpURLConnection;
import java.net.URI;
import java.net.URL;

/**
 * Description:  TODO
 * Author: admin
 * CreateDate: 2021/4/8 11:04
 */
public class RequestBuilder {

    private boolean isCancel;
    private Context mContext;
    Status status = Status.STATUS_READY;
    private Reference<PixelMap> reference;

    RequestBuilder(Context context) {
        this.mContext = context;
    }

    public PixelMap getPixelMap() {
        return reference == null ? null : reference.get();
    }

    private void setPixelMap(PixelMap pixelMap) {
        this.reference = new SoftReference<>(pixelMap);
    }

    public boolean isCancel() {
        return isCancel;
    }

    public void setCancel(boolean cancel) {
        isCancel = cancel;
    }


    private void urlToPixelMap(URL url, Image component, ImageLoaderListener loaderListener) {
        this.status = Status.STATUS_READY;
        ThreadUtils.execute(() -> {
            NetManager instance = NetManager.getInstance(mContext);
            if (!instance.hasDefaultNet()) {
                return;
            }
            LogUtils.d("开启网络请求,url = %s", url.toString());
            NetHandle defaultNet = instance.getDefaultNet();
            InputStream resource = null;
            HttpURLConnection urlConnection;
            try {
                urlConnection = (HttpURLConnection) defaultNet.openConnection(url);
                urlConnection.setRequestMethod("GET");
                urlConnection.setReadTimeout(30 * 1000);
                urlConnection.setConnectTimeout(10 * 1000);
                urlConnection.connect();
                int code = urlConnection.getResponseCode();
                LogUtils.d("网络请求返回 Code = %d", code);
                if (code == 200) {
                    if (isCancel()) {
                        LogUtils.i("加载资源已经手动取消,url = %s", url);
                        setCancel(false);
                        urlConnection.disconnect();
                        status = Status.STATUS_END;
                        if (loaderListener != null) {
                            loaderListener.onLoadingCancelled(url, component);
                        }
                        return;
                    }
                    status = Status.STATUS_LOADING;
                    resource = urlConnection.getInputStream();
                    ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
                    sourceOptions.formatHint = "image/jpg";

                    ImageSource imageSource = ImageSource.create(resource, sourceOptions);
                    ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
                    PixelMap pixelMap = imageSource.createPixelmap(options);
                    LogUtils.d("网络数据转换 PixelMap = %s", pixelMap == null ? "null" : "" + pixelMap.getPixelBytesNumber());
                    //添加缓存
                    setPixelMap(pixelMap);
                    mContext.getUITaskDispatcher().asyncDispatch(() -> {
                        if (isCancel()) {
                            LogUtils.i("加载资源已经手动取消,url = %s", url);
                            setCancel(false);
                            status = Status.STATUS_END;
                            if (loaderListener != null) {
                                loaderListener.onLoadingCancelled(url, component);
                            }
                        } else {
                            component.setPixelMap(pixelMap);
                            status = Status.STATUS_END;
                            if (loaderListener != null) {
                                loaderListener.onLoadingComplete(url, component);
                            }
                        }
                    });
                }
            } catch (IOException e) {
                LogUtils.e(e.getLocalizedMessage());
                status = Status.STATUS_END;
                if (loaderListener != null) {
                    loaderListener.onLoadingFailed(url, component);
                }
            } finally {
                if (resource != null) {
                    try {
                        resource.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }
        });
    }

    void loadResource(Object obj, Image component, Integer placeholder, ImageLoaderListener loaderListener) {
        if (loaderListener != null) {
            loaderListener.onLoadingStarted(obj, component);
        }
        //设置加载占位符
        if (placeholder != null && placeholder > 0) {
            component.setPixelMap(placeholder);
        }
        mContext.getUITaskDispatcher().asyncDispatch(() -> {
            try {
                if (isCancel()) {
                    LogUtils.i("加载资源已经手动取消,obj = %s", getKey(obj));
                    setCancel(false);
                    status = Status.STATUS_END;
                    if (loaderListener != null) {
                        loaderListener.onLoadingCancelled(obj, component);
                    }
                } else {
                    status = Status.STATUS_LOADING;
                    PixelMap pixelMap = getPixelMap();
                    if (pixelMap == null) {
                        LogUtils.i("加载资源缓存为空,开始加载资源...");
                        if (obj instanceof File) {
                            pixelMap = fileToPixelMap((File) obj);
                        } else if (obj instanceof Integer) {
                            pixelMap = resToPixelMap((Integer) obj);
                        } else if (obj instanceof String) {
                            URI uri = URI.create((String) obj);
                            LogUtils.i("加载地址URI:%s", new Gson().toJson(uri));
                            if (!TextUtils.isEmpty(uri.getScheme())) {
                                urlToPixelMap(uri.toURL(), component, loaderListener);
                            } else {
                                pixelMap = fileToPixelMap(new File(uri.getPath()));
                            }
                        }
                        setPixelMap(pixelMap);
                    }
                    LogUtils.i("即将完成资源设置,PixelMap = %s", pixelMap == null ? "null" : "" + pixelMap.getPixelBytesNumber());
                    if (pixelMap != null) {
                        component.setPixelMap(pixelMap);
                        status = Status.STATUS_END;
                        if (loaderListener != null) {
                            loaderListener.onLoadingComplete(obj, component);
                        }
                    }
                }
            } catch (Exception e) {
                LogUtils.e(e.getLocalizedMessage());
                status = Status.STATUS_END;
                if (loaderListener != null) {
                    loaderListener.onLoadingFailed(obj, component);
                }
            }

        });
    }

    private PixelMap resToPixelMap(int res) throws Exception {
        InputStream resource = mContext.getResourceManager().getResource(res);
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/jpg";
        ImageSource imageSource = ImageSource.create(resource, sourceOptions);
        ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
        return imageSource.createPixelmap(options);
    }


    private PixelMap fileToPixelMap(File file) throws Exception {
        ImageSource.SourceOptions sourceOptions = new ImageSource.SourceOptions();
        sourceOptions.formatHint = "image/jpg";
        ImageSource imageSource = ImageSource.create(file, sourceOptions);
        ImageSource.DecodingOptions options = new ImageSource.DecodingOptions();
        return imageSource.createPixelmap(options);
    }

    private String getKey(Object obj) {
        String key = null;
        if (obj instanceof Integer) {
            key = obj + "";
        } else if (obj instanceof String) {
            key = (String) obj;
        } else if (obj instanceof URL) {
            key = ((URL) obj).toString();
        } else if (obj instanceof File) {
            key = ((File) obj).getAbsolutePath();
        }
        return key;
    }

    enum Status {
        STATUS_READY,
        STATUS_LOADING,
        STATUS_END
    }

}
